package junit.generic.genetic.chromosome;

import static org.junit.Assert.*;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import generic.genetic.chromosome.PermutationChromosome;

import org.junit.Test;

public class PermutationChromosome_Crossover_Test {

	PermutationChromosome pc1;
	PermutationChromosome pc2;

	public PermutationChromosome_Crossover_Test(){
		pc1 = new PermutationChromosome(20);		
		pc2 = new PermutationChromosome(20);
	}
	
	@Test
	public void cross_PMX_test() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		//assert example
		
		pc1 = new PermutationChromosome(9);
		pc2 = new PermutationChromosome(9);
		
		pc1.setPermutation(new int[]{1,2,3,4,5,6,7,8,9});
		pc2.setPermutation(new int[]{4,5,2,1,8,7,6,9,3});
		
		
		Method method = PermutationChromosome.class.getDeclaredMethod("cross_PMX", PermutationChromosome.class, int.class, int.class);
		method.setAccessible(true);
		method.invoke(pc1,pc2,3,7);
		
		PermutationChromosome pc1_exp = (PermutationChromosome) pc1.getCopy();
		PermutationChromosome pc2_exp = (PermutationChromosome) pc2.getCopy();
		
		pc1_exp.setPermutation(new int[]{4,2,3,1,8,7,6,5,9});
		pc2_exp.setPermutation(new int[]{1,8,2,4,5,6,7,9,3});
		
		assertEquals("El cromosoma 1 resultante no es correcto", pc1_exp, pc1);
		assertEquals("El cromosoma 2 resultante no es correcto", pc2_exp, pc2);
		
	}
	
	@Test
	public void cross_OX_test() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		//assert example
		
		pc1 = new PermutationChromosome(9);
		pc2 = new PermutationChromosome(9);
				
		pc1.setPermutation(new int[]{1,2,3,4,5,6,7,8,9});
		pc2.setPermutation(new int[]{4,5,2,1,8,7,6,9,3});
		
		Method method = PermutationChromosome.class.getDeclaredMethod("cross_OX", PermutationChromosome.class, int.class, int.class);
		method.setAccessible(true);
		method.invoke(pc1,pc2,3,7);
		
		PermutationChromosome pc1_exp = (PermutationChromosome) pc1.getCopy();
		PermutationChromosome pc2_exp = (PermutationChromosome) pc2.getCopy();
				
		pc1_exp.setPermutation(new int[]{3,4,5,1,8,7,6,9,2});
		pc2_exp.setPermutation(new int[]{2,8,1,4,5,6,7,9,3});
		
		assertEquals("El cromosoma 1 resultante no es correcto", pc1_exp, pc1);
		assertEquals("El cromosoma 2 resultante no es correcto", pc2_exp, pc2);
		
	}
	
	@Test
	public void cross_OX_h_ord_test() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		//assert example
		
		pc1 = new PermutationChromosome(9);
		pc2 = new PermutationChromosome(9);
				
		pc1.setPermutation(new int[]{1,2,3,4,5,6,7,8,9});
		pc2.setPermutation(new int[]{4,5,2,1,8,7,6,9,3});
		
		Method method = PermutationChromosome.class.getDeclaredMethod("cross_OX_ord_priority", PermutationChromosome.class, int[].class);
		method.setAccessible(true);
		method.invoke(pc1,pc2,new int[]{2,3,5,8});
		
		PermutationChromosome pc1_exp = (PermutationChromosome) pc1.getCopy();
		PermutationChromosome pc2_exp = (PermutationChromosome) pc2.getCopy();
				
		pc1_exp.setPermutation(new int[]{3,5,2,1,8,7,4,6,9});
		pc2_exp.setPermutation(new int[]{2,1,7,4,5,6,3,8,9});
		
		assertEquals("El cromosoma 1 resultante no es correcto", pc1_exp, pc1);
		assertEquals("El cromosoma 2 resultante no es correcto", pc2_exp, pc2);
		
	}
	
	@Test
	public void cross_CX_test1() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		//assert example
		
		pc1 = new PermutationChromosome(9);
		pc2 = new PermutationChromosome(9);
		
		pc1.setPermutation(new int[]{1,2,3,4,5,6,7,8,9});
		pc2.setPermutation(new int[]{4,1,2,8,7,6,9,3,5});
		
		Method method = PermutationChromosome.class.getDeclaredMethod("cross_CX", PermutationChromosome.class);
		method.setAccessible(true);
		method.invoke(pc1,pc2);
		
		PermutationChromosome pc1_exp = (PermutationChromosome) pc1.getCopy();
		PermutationChromosome pc2_exp = (PermutationChromosome) pc2.getCopy();
				
		pc1_exp.setPermutation(new int[]{1,2,3,4,7,6,9,8,5});
		pc2_exp.setPermutation(new int[]{4,1,2,8,5,6,7,3,9});
		
		assertEquals("El cromosoma 1 resultante no es correcto", pc1_exp, pc1);
		assertEquals("El cromosoma 2 resultante no es correcto", pc2_exp, pc2);
		
	}
	
	@Test
	public void cross_CX_test2() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		//assert example
		
		pc1 = new PermutationChromosome(9);
		pc2 = new PermutationChromosome(9);
		
		pc1.setPermutation(new int[]{0,1,2,3,4,5,6,7,8});
		pc2.setPermutation(new int[]{3,0,1,7,6,5,8,2,4});
		
		Method method = PermutationChromosome.class.getDeclaredMethod("cross_CX", PermutationChromosome.class);
		method.setAccessible(true);
		method.invoke(pc1,pc2);
		
		PermutationChromosome pc1_exp = (PermutationChromosome) pc1.getCopy();
		PermutationChromosome pc2_exp = (PermutationChromosome) pc2.getCopy();
				
		pc1_exp.setPermutation(new int[]{0,1,2,3,6,5,8,7,4});
		pc2_exp.setPermutation(new int[]{3,0,1,7,4,5,6,2,8});
		
		assertEquals("El cromosoma 1 resultante no es correcto", pc1_exp, pc1);
		assertEquals("El cromosoma 2 resultante no es correcto", pc2_exp, pc2);
		
	}
	
	@Test
	public void cross_CX_test3() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		//assert example
		
		pc1 = new PermutationChromosome(5);
		pc2 = new PermutationChromosome(5);
		
		pc1.setPermutation(new int[]{2,4,3,0,1});
		pc2.setPermutation(new int[]{3,1,4,0,2});
		
		Method method = PermutationChromosome.class.getDeclaredMethod("cross_CX", PermutationChromosome.class);
		method.setAccessible(true);
		method.invoke(pc1,pc2);
		
		PermutationChromosome pc1_exp = (PermutationChromosome) pc1.getCopy();
		PermutationChromosome pc2_exp = (PermutationChromosome) pc2.getCopy();
				
		pc1_exp.setPermutation(new int[]{2,4,3,0,1});
		pc2_exp.setPermutation(new int[]{3,1,4,0,2});
		
		assertEquals("El cromosoma 1 resultante no es correcto", pc1_exp, pc1);
		assertEquals("El cromosoma 2 resultante no es correcto", pc2_exp, pc2);
		
	}
	
	@Test
	public void cross_Ordinal_test() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		//assert example
		
		pc1 = new PermutationChromosome(9);
		pc2 = new PermutationChromosome(9);
		
		pc1.setPermutation(new int[]{3,4,1,0,7,6,5,8,2});
		pc2.setPermutation(new int[]{0,1,2,3,4,5,6,7,8});
		
		Method method = PermutationChromosome.class.getDeclaredMethod("cross_Ordinal", PermutationChromosome.class, int.class);
		method.setAccessible(true);
		method.invoke(pc1,pc2,4);
		
		PermutationChromosome pc1_exp = (PermutationChromosome) pc1.getCopy();
		PermutationChromosome pc2_exp = (PermutationChromosome) pc2.getCopy();
				
		pc1_exp.setPermutation(new int[]{3,4,1,0,2,5,6,7,8});
		pc2_exp.setPermutation(new int[]{0,1,2,3,7,6,5,8,4});
		
		assertEquals("El cromosoma 1 resultante no es correcto", pc1_exp, pc1);
		assertEquals("El cromosoma 2 resultante no es correcto", pc2_exp, pc2);
		
	}
	
}
